<?php

/**
 * Fastapp.
 * 3/7/24
 * @Author deepsea
 * @Contact telegram:deepsea159
 */

namespace App\Fastapp\Api\Controller\Account;

use App\Fastapp\Api\Controller\ApiController;
use App\Fastapp\Api\Service\Account\AccountService;
use App\Fastapp\Aspect\ApiAuth;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\RateLimit\Annotation\RateLimit;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
use Psr\Http\Message\ResponseInterface;

#[Controller(prefix: 'api/account')]
class AccountController extends ApiController
{
    #[Inject]
    public AccountService $service;

    #[Inject]
    protected ValidatorFactoryInterface $validatorFactory;

    public function validate(array $rule, array $message = []): array
    {
        return $this->validatorFactory->make($this->request->all(), $rule, $message)->validate();
    }

    #[PostMapping('loginByPassword')]
    public function loginByPassword(): ResponseInterface
    {
        return $this->success($this->service->loginByPassword($this->validate([
            'username' => 'required',
            'password' => 'required',
            'push_client' => 'string',
        ], ['username.*' => fastapp_t('account.v_1'), 'password.*' => fastapp_t('account.v_2')])));
    }

    #[PostMapping('loginByVcode')]
    public function loginByVcode(): ResponseInterface
    {
        return $this->success($this->service->loginByVcode($this->validate([
            'code' => 'required|numeric',
            'mobile' => 'required|regex:/^1[3-9]\d{9}$/',
            'vcode' => 'required',
            'push_client' => 'string',
        ], ['vcode.*' => fastapp_t('account.v_3')])));
    }

    #[PostMapping('registerByVcode')]
    public function registerByVcode(): ResponseInterface
    {
        return $this->success($this->service->registerByVcode($this->validate([
            'email' => 'email',
            'code' => 'required|numeric',
            'mobile' => 'required|regex:/^1[3-9]\d{9}$/',
            'vcode' => 'required',
            'password' => 'string|min:8',
            'push_client' => 'string',
            'name' => 'string',
            'invite_code' => 'string',
        ], ['vcode.*' => fastapp_t('account.v_3')])));
    }

    #[PostMapping('registerByUsername')]
    public function registerByUsername(): ResponseInterface
    {
        return $this->success($this->service->registerByUsername($this->validate([
            'username' => 'required|min:6|max:32',
            'password' => 'required|min:6|max:32|confirmed',
            'password_confirmation' => 'required',
            'name' => 'string',
            'invite_code' => 'string',
            'push_client' => 'string',
        ], ['username.*' => fastapp_t('account.v_4')])));
    }

    #[PostMapping('registerByEmail')]
    public function registerByEmail(): ResponseInterface
    {
        return $this->success($this->service->registerByEmail($this->validate([
            'email' => 'required|min:6|max:32|email',
            'password' => 'required|min:6|max:32|confirmed',
            'password_confirmation' => 'required',
            'vcode' => 'required',
            'nickname' => 'string',
            'invite_code' => 'string',
            'push_client' => 'string',
        ], ['username.*' => fastapp_t('account.v_4')])));
    }

    #[PostMapping('checkAccount')]
    public function checkAccount(): ResponseInterface
    {
        return $this->success($this->service->checkAccount($this->validate([
            'username' => 'required_if:type,1|regex:/^1[3-9]\d{9}$/',
            'code' => 'required_if:type,2|numeric',
            'mobile' => 'required_if:type,2|regex:/^1[3-9]\d{9}$/',
            'email' => 'required_if:type,3|email',
            'type' => 'required|in:1,2,3',
        ])));
    }

    #[PostMapping('changePassword'), ApiAuth]
    public function changePassword(): ResponseInterface
    {
        $this->service->changePassword($this->validate([
            'original_password' => 'required|min:6|string',
            'password' => 'required|min:6|max:32|confirmed',
            'password_confirmation' => 'required',
        ], [
            'original_password.*' => fastapp_t('account.v_5'),
            'password.required' => fastapp_t('account.v_6'),
            'password.min' => fastapp_t('account.v_7'),
            'password.confirmed' => fastapp_t('account.v_8'),
        ]));
        return $this->success();
    }

    #[PostMapping('unsubscribe'), ApiAuth]
    public function unsubscribe(): ResponseInterface
    {
        $this->service->unsubscribe($this->validate([
            'mobile' => 'required|regex:/^1[3-9]\d{9}$/',
            'vcode' => 'required',
        ]));
        return $this->success();
    }

    #[GetMapping('info'), ApiAuth]
    public function info(): ResponseInterface
    {
        return $this->success($this->service->info());
    }

    #[PostMapping('updateInfo'), ApiAuth]
    public function updateInfo(): ResponseInterface
    {
        return $this->success($this->service->updateInfo($this->request->all()));
    }

    #[PostMapping('logout'), ApiAuth]
    public function logout(): ResponseInterface
    {
        user(fastapp_header('app-source', 'h5'))->getJwt()->logout();
        return $this->success();
    }

    #[PostMapping('refresh'), ApiAuth]
    public function refresh(): ResponseInterface
    {
        return $this->success(['token' => user('api')->refresh()]);
    }

    #[PostMapping('loginByWx')]
    public function loginByWx(): ResponseInterface
    {
        return $this->success($this->service->loginByWx($this->validate([
            'js_code' => 'string|required',
            'code' => 'required|numeric',
            'related_type' => 'required|integer',
            'mobile' => 'required|regex:/^1[3-9]\d{9}$/',
        ])));
    }

    #[PostMapping('bindWx')]
    public function bindWx(): ResponseInterface
    {
        return $this->success($this->service->bindWx($this->validate([
            'unique_code' => 'string|required',
            'code' => 'required|numeric',
            'related_type' => 'required|integer',
            'mobile' => 'required|regex:/^1[3-9]\d{9}$/',
            'nickname' => 'string',
            'avatar' => 'string',
            'vcode' => 'required',
        ])));
    }

    #[PostMapping('setCache')]
    public function setCache(): ResponseInterface
    {
        return $this->success($this->service->setCache($this->validate([
            'field' => 'required|in:currency,gameid',
            'val' => 'required|string|max:32',
        ])));
    }

    #[GetMapping('sendVcode'), RateLimit(create: 3, capacity: 5)]
    public function sendVcode(): ResponseInterface
    {
        $this->service->sendVcode($this->validate([
            'mobile' => 'required_if:type,1|regex:/^1[3-9]\d{9}$/',
            'code' => 'required_if:type,1|numeric',
            'email' => 'required_if:type,2|email',
            'type' => 'required|in:1,2'
        ], [
            'mobile.*' => fastapp_t('account.v_9'),
            'code.*' => fastapp_t('account.v_10'),
        ]));
        return $this->success();
    }

    #[PostMapping('bindEmail')]
    public function bindEmail(): ResponseInterface
    {
        $data = $this->validate(['email' => 'required|email', 'vcode' => 'required']);
        $this->service->bindEmail($data['email'], $data['vcode']);
        return $this->success();
    }

    #[PostMapping('bindMobile')]
    public function bindMobile(): ResponseInterface
    {
        $data = $this->validate(['code' => 'required|numeric', 'mobile' => 'required|regex:/^1[3-9]\d{9}$/', 'vcode' => 'required']);
        $this->service->bindMobile($data['code'], $data['mobile'], $data['vcode']);
        return $this->success();
    }

    #[GetMapping('sendBindMobileVcode')]
    public function sendBindMobileVcode(): ResponseInterface
    {
        $this->service->sendBindMobileVcode();
        return $this->success();
    }

    #[GetMapping('sendBindEmailVcode')]
    public function sendBindEmailVcode(): ResponseInterface
    {
        $this->service->sendBindEmailVcode();
        return $this->success();
    }

    #[PostMapping('changeMobile'), ApiAuth]
    public function changeMobile(): ResponseInterface
    {
        $this->service->changeMobile($this->validate([
            'code' => 'required|numeric',
            'mobile' => 'required|regex:/^1[3-9]\d{9}$/',
            'newmobile' => 'required|regex:/^1[3-9]\d{9}$/',
            'vcode' => 'required',
        ], [
            'mobile.*' => fastapp_t('account.v_9'),
            'code.*' => fastapp_t('account.v_10'),
            'newmobile.*' => fastapp_t('account.v_11'),
            'vcode.*' => fastapp_t('account.v_3'),
        ]));
        return $this->success();
    }

    #[PostMapping('changeEmail'), ApiAuth]
    public function changeEmail(): ResponseInterface
    {
        $this->service->changeEmail($this->validate([
            'email' => 'required|email',
            'vcode' => 'required',
        ], [
            'vcode.*' => fastapp_t('account.v_3'),
        ]));
        return $this->success();
    }

    #[PostMapping('setTransactionPassword')]
    public function setTransactionPassword(): ResponseInterface
    {
        return $this->service->setTransactionPassword($this->validate([
            'password' => 'required|string|max:6|confirmed',
            'password_confirmation' => 'required',
        ])['password']) ? $this->success() : $this->error();
    }

    #[PostMapping('resetTransactionPassword')]
    public function resetTransactionPassword(): ResponseInterface
    {
        $this->service->resetTransactionPassword($this->validate([
            'password' => 'required|string|max:6|confirmed',
            'password_confirmation' => 'required',
            'type' => 'required|in:1,2,3,4',
            'vcode' => 'required',
        ]));
        return $this->success();
    }

    #[PostMapping('checkTransactionPassword')]
    public function checkTransactionPassword(): ResponseInterface
    {
        return $this->success($this->service::checkTransactionPassword($this->validate([
            'password' => 'required',
        ])['password']));
    }

    #[PostMapping('loginByTelegram')]
    public function loginByTelegram(): ResponseInterface
    {
        return $this->success($this->service->loginByTelegram($this->validate([
            'login_type' => 'in:1,2',
            'id' => 'required_if:login_type,1',
            'first_name' => 'required_if:login_type,1',
            'username' => 'required_if:login_type,1',
            'auth_date' => 'required_if:login_type,1',
            'hash' => 'required',
            'direct' => 'in:0,1',
        ])));
    }

    #[PostMapping('bindTelegram')]
    public function bindTelegram(): ResponseInterface
    {
        return $this->success($this->service->bindTelegram($this->request->all()));
    }

    #[PostMapping('checkVcode')]
    public function checkVcode(): ResponseInterface
    {
        $this->validate(['vcode' => 'required', 'key' => 'required', 'type' => 'required', 'code' => 'string']);
        return $this->success($this->service->checkVcode($this->request->all()));
    }

    #[PostMapping('resetPassword')]
    public function resetPassword(): ResponseInterface
    {
        $this->validate([
            'type' => 'required',
            'code' => 'string',
            'key' => 'required',
            'vcode' => 'required',
            'password' => 'required|min:6|max:32|confirmed',
            'password_confirmation' => 'required',
        ]);
        return $this->service->resetPassword($this->request->all()) ? $this->success() : $this->error();
    }

    #[PostMapping('loginByAddress')]
    public function loginByAddress(): ResponseInterface
    {
        $data = $this->validate([
            'symbol' => 'required|in:TON,ETH,TRX,BNB',
            'address' => 'required',
        ]);
        return $this->success($this->service->loginByAddress($data['symbol'], $data['address']));
    }
}